/**
 * Framework for batch testing user profile models
 * Final project by Sergey Nepomnyachiy and Julia Polchin
 * Supervisor: Tsvi Kuflik
 *
 */
package models.collaborative;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;

import org.junit.Test;

import core.generators.CSVGenerator;

/**
 * @author Sergey and Julia
 * 
 */
public class TestCollaborative {

	/**
	 * 
	 */
	@SuppressWarnings("boxing")
	@Test
	public void testFormulae() {
		Double arr[] = { 1.0, 1.0, 1.0, 1.0 };
		Vector<Double> vec1 = new Vector<Double>();
		for (Double d : arr)
			vec1.add(d);
		assertEquals(Formulae.norm(vec1), 2.0);
		assertEquals(Formulae.dotProd(vec1, vec1), 4.0);
		assertEquals(Formulae.cosine(vec1, vec1), 0.0);
	}

	/**
	 * 
	 */
	@SuppressWarnings( { "boxing", "unused" })
	@Test
	public void testKNN() {

		Double arr[] = { 1.0, 2.0, 3.0, 4.0 };
		Double arr2[] = { 1.0, 2.0, 3.0, 0.0 };
		Vector<Double> vec1 = new Vector<Double>();
		Vector<Double> vec2 = new Vector<Double>();
		for (Double d : arr)
			vec1.add(d);
		for (Double d : arr2)
			vec2.add(d);

		Double r1 = Formulae.cosine(vec1, vec2);
		assertTrue(r1.equals(0.8187562376025609));

		Vector<Vector<Double>> matrix = new Vector<Vector<Double>>();
		for (Double d : arr)
			matrix.add(vec1);
		matrix.add(vec2);

		KNN knn4 = new KNN(matrix, 4);
		KNN knn3 = new KNN(matrix, 3);
		KNN knn2 = new KNN(matrix, 2);

		Vector<Double> rvec;

		rvec = knn4.getNearestOne(vec2);
		assertTrue(rvec.elementAt(3).equals(3.0));
		rvec = knn3.getNearestOne(vec2);
		assertTrue(rvec.elementAt(3).equals(8.0 / 3.0));
		rvec = knn2.getNearestOne(vec2);
		assertTrue(rvec.elementAt(3).equals(2.0));

	}

	/**
	 * 
	 */
	@SuppressWarnings( { "boxing", "unused" })
	@Test
	public void testCollaborative() {
		Double arr[] = { 1.0, 2.0, 3.0, 4.0 };
		Double arr2[] = { 1.0, 2.0, 3.0 };
		Vector<Double> vec1 = new Vector<Double>();
		Vector<Double> vec2 = new Vector<Double>();
		for (Double d : arr)
			vec1.add(d);
		for (Double d : arr2)
			vec2.add(d);

		Facade facade = new Facade(0);
		Facade.injectConstants(3);
		//create indices vector -- empty because we don't want to remove  thing
		Vector<Integer> indices = new Vector<Integer>();
		
		for (Double d : arr)
			Facade.addUser(Facade.convertVector(vec1),Facade.convertVector(indices));
		int ind = 0;
		for (Double d : arr2) {
			facade.trainUser(ind,d);
			ind++;
		}
		for (int i = 0; i < 4; ++i) {
			Double prediction = facade.predict(i);
			assertTrue(prediction.equals(arr[i]));
		}

	}

	/**
	 * 
	 */
	@SuppressWarnings( { "unchecked", "boxing" })
	@Test
	public void stressTest() {
		File file = new File("collab.csv");
		CSVGenerator csv = new CSVGenerator(file);

		Facade facade = new Facade(0);
		Facade.injectConstants(3);
		Facade.clearAll();
		Collection<?> matrix = csv.getVector();
		Iterator<?> it = matrix.iterator();

		for (int i = 0; i < 100; ++i) {
			Vector<Object> v = (Vector<Object>) it.next();
			Facade.addUser(Facade.convertVector(v), Facade.convertVector(new Vector<Integer>()));
		}

		Vector<Object> user = (Vector<Object>) it.next();

		for (int i = 0; i < 90; i++)
			facade.trainUser(i,(Double) user.elementAt(i));

		for (int i = 91; i < 100; i++) {
			Double d = facade.predict(i);
			System.out.print(d);
			System.out.print(",");
			System.out.println(user.elementAt(i));
			assertTrue(!d.equals(0.0));
		}

	}

}
